🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / feature / map / src / commonMain / kotlin / org / meshtastic / feature / map / geojson / IconUrls.kt
Displaying Raw • Download
feature/map/src/commonMain/kotlin/org/meshtastic/feature/map/geojson/IconUrls.kt renovate/fastlane-2.x-lockfile (423f9d44) Text, 5.38 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.feature.map.geojson
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787kotlinx.serialization.json.Json
Tff7b72import T7ee787kotlinx.serialization.json.JsonArray
Tff7b72import T7ee787kotlinx.serialization.json.JsonElement
Tff7b72import T7ee787kotlinx.serialization.json.JsonObject
Tff7b72import T7ee787kotlinx.serialization.json.JsonPrimitive
Tff7b72import T7ee787kotlinx.serialization.json.jsonArray
Tff7b72import T7ee787kotlinx.serialization.json.jsonObject
Tff7b72import T7ee787org.meshtastic.feature.map.kml.ICON_URL_PROPERTY
T8b949e/**
* More distinct icons than one imported layer will be given style images for.
*
* Every icon becomes an image uploaded into the map style and held for as long as the layer is shown, so an import with
* a per-feature icon would otherwise be an unbounded upload. Well past what a hand-made overlay carries.
*/
Tff7b72private Tff7b72const Tff7b72val Te6edf3MAX_ICONS Tff7b72= T79c0ff6T79c0ff4
T8b949e/**
* The distinct icon images a GeoJSON document asks for.
*
* The renderer has to know these before it composes: MapLibre picks an icon per feature from a `case` over the values
* it was given, and there is no way to register an image under a name chosen later — `ImageManager`'s acquire methods
* are internal to the library. So the document is read once, here, rather than left to the map to discover.
*
* Returns nothing for a document that will not parse. An import that cannot be read is already drawing nothing; the
* renderer falling back to plain points is the better failure than no layer at all.
*/
Tff7b72fun Td2a8ffgeoJsonIconUrlsTb4b4b4(Te6edf3geoJsonTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3SetTff7b72<Tffa657StringTff7b72> Tff7b72= Te6edf3readIconUrlsTb4b4b4(Te6edf3geoJsonTb4b4b4, Tff7b72::Te6edf3sanitizeImportedIconUrlTb4b4b4)
T8b949e/**
* Relative icon references from the caller's own rewritten GeoJSON (e.g. cache `file://` URIs) rather than user input.
*/
Tff7b72fun Td2a8fftrustedGeoJsonIconUrlsTb4b4b4(Te6edf3geoJsonTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3SetTff7b72<Tffa657StringTff7b72> Tff7b72=
Te6edf3readIconUrlsTb4b4b4(Te6edf3geoJsonTb4b4b4) Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3trimTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3takeIfTb4b4b4(Tffa657StringTff7b72::Te6edf3isNotEmptyTb4b4b4) Tb4b4b4}
T8b949e/**
* Imported layers may name icons only by an archive-relative path. Absolute URIs would make the app fetch arbitrary
* network or local resources during rendering, so they are stripped.
*/
Tff7b72fun Td2a8ffsanitizeImportedIconUrlTb4b4b4(Te6edf3urlTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Tffa657String? Tb4b4b4{
Tff7b72val Te6edf3trimmed Tff7b72= Te6edf3urlTb4b4b4.Te6edf3trimTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3trimmed
Tb4b4b4.Te6edf3takeIf Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4) Tb4b4b4}
Tff7b72?.Te6edf3takeUnless Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff'/'Tb4b4b4) Tff7b72|Tff7b72| Tffa657itTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"Ta5d6ff//Ta5d6ff"Tb4b4b4) Tff7b72|Tff7b72| Te6edf3URI_SCHEME_PREFIXTb4b4b4.Te6edf3containsMatchInTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tb4b4b4}
T8b949e/** Rewrites `icon-url` properties without disturbing unrelated properties or feature order. */
Tff7b72fun Td2a8ffrewriteGeoJsonIconUrlsTb4b4b4(Te6edf3geoJsonTb4b4b4: Tffa657StringTb4b4b4, Te6edf3replacementsTb4b4b4: Te6edf3MapTff7b72<Tffa657StringTb4b4b4, Tffa657StringTff7b72>Tb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Tff7b72if Tb4b4b4(Te6edf3replacementsTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3geoJson
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72val Te6edf3root Tff7b72= Te6edf3JsonTb4b4b4.Te6edf3parseToJsonElementTb4b4b4(Te6edf3geoJsonTb4b4b4)Tb4b4b4.Te6edf3jsonObject
Tff7b72val Te6edf3features Tff7b72= Te6edf3rootTff7b72[Ta5d6ff"Ta5d6fffeaturesTa5d6ff"Tff7b72]Tff7b72?.Te6edf3jsonArray
Tff7b72if Tb4b4b4(Te6edf3features Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3geoJson
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72val Te6edf3rewrittenFeatures Tff7b72= Te6edf3JsonArrayTb4b4b4(Te6edf3featuresTb4b4b4.Te6edf3map Tb4b4b4{ Te6edf3feature Tff7b72-Tff7b72> Te6edf3rewriteIconUrlTb4b4b4(Te6edf3featureTb4b4b4, Te6edf3replacementsTb4b4b4) Tb4b4b4}Tb4b4b4)
Te6edf3JsonTb4b4b4.Te6edf3encodeToStringTb4b4b4(Te6edf3JsonObjectTb4b4b4(Te6edf3root Tff7b72+ Tb4b4b4(Ta5d6ff"Ta5d6fffeaturesTa5d6ff" Te6edf3to Te6edf3rewrittenFeaturesTb4b4b4)Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3IllegalArgumentExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3withTagTb4b4b4(Te6edf3TAGTb4b4b4)Tb4b4b4.Te6edf3wTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffCould not rewrite icons in an imported layerTa5d6ff" Tb4b4b4}
Te6edf3geoJson
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffreadIconUrlsTb4b4b4(Te6edf3geoJsonTb4b4b4: Tffa657StringTb4b4b4, Te6edf3transformTb4b4b4: Tb4b4b4(Tffa657StringTb4b4b4) Tff7b72-Tff7b72> Tffa657String?Tb4b4b4)Tb4b4b4: Te6edf3SetTff7b72<Tffa657StringTff7b72> Tff7b72= Tff7b72try Tb4b4b4{
Te6edf3JsonTb4b4b4.Te6edf3parseToJsonElementTb4b4b4(Te6edf3geoJsonTb4b4b4)
Tb4b4b4.Te6edf3jsonObjectTff7b72[Ta5d6ff"Ta5d6fffeaturesTa5d6ff"Tff7b72]
Tff7b72?.Te6edf3jsonArray
Tb4b4b4.Te6edf3orEmptyTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3asSequenceTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3mapNotNullTb4b4b4(Tff7b72::Te6edf3propertiesOfTb4b4b4)
Tb4b4b4.Te6edf3mapNotNullTb4b4b4(Tff7b72::Te6edf3iconUrlOfTb4b4b4)
Tb4b4b4.Te6edf3mapNotNullTb4b4b4(Te6edf3transformTb4b4b4)
Tb4b4b4.Te6edf3distinctTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3takeTb4b4b4(Te6edf3MAX_ICONSTb4b4b4)
Tb4b4b4.Te6edf3toSetTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3IllegalArgumentExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3withTagTb4b4b4(Te6edf3TAGTb4b4b4)Tb4b4b4.Te6edf3wTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffCould not read icons from an imported layerTa5d6ff" Tb4b4b4}
Te6edf3emptySetTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffrewriteIconUrlTb4b4b4(Te6edf3featureTb4b4b4: Te6edf3JsonElementTb4b4b4, Te6edf3replacementsTb4b4b4: Te6edf3MapTff7b72<Tffa657StringTb4b4b4, Tffa657StringTff7b72>Tb4b4b4)Tb4b4b4: Te6edf3JsonElement Tff7b72=
Tb4b4b4(Te6edf3feature Tff7b72as? Te6edf3JsonObjectTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3objectValue Tff7b72-Tff7b72>
Te6edf3propertiesOfTb4b4b4(Te6edf3objectValueTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3properties Tff7b72-Tff7b72>
Te6edf3iconUrlOfTb4b4b4(Te6edf3propertiesTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3current Tff7b72-Tff7b72>
Te6edf3replacementsTff7b72[Te6edf3currentTff7b72]Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3rewritten Tff7b72-Tff7b72>
Tff7b72val Te6edf3rewrittenProperties Tff7b72= Te6edf3JsonObjectTb4b4b4(Te6edf3properties Tff7b72+ Tb4b4b4(Te6edf3ICON_URL_PROPERTY Te6edf3to Te6edf3JsonPrimitiveTb4b4b4(Te6edf3rewrittenTb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3JsonObjectTb4b4b4(Te6edf3objectValue Tff7b72+ Tb4b4b4(Ta5d6ff"Ta5d6ffpropertiesTa5d6ff" Te6edf3to Te6edf3rewrittenPropertiesTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72?: Te6edf3feature
Tff7b72private Tff7b72fun Td2a8ffpropertiesOfTb4b4b4(Te6edf3featureTb4b4b4: Te6edf3JsonElementTb4b4b4)Tb4b4b4: Te6edf3JsonObject? Tff7b72= Tb4b4b4(Te6edf3feature Tff7b72as? Te6edf3JsonObjectTb4b4b4)Tff7b72?.Te6edf3getTb4b4b4(Ta5d6ff"Ta5d6ffpropertiesTa5d6ff"Tb4b4b4) Tff7b72as? Te6edf3JsonObject
Tff7b72private Tff7b72fun Td2a8fficonUrlOfTb4b4b4(Te6edf3propertiesTb4b4b4: Te6edf3JsonObjectTb4b4b4)Tb4b4b4: Tffa657String? Tff7b72=
T8b949e// `as?` rather than the `jsonPrimitive` accessor, which throws: an import is free to put an object or a
T8b949e// number where a URL belongs, and one such feature must not cost the layer its other icons.
Tb4b4b4(Te6edf3propertiesTff7b72[Te6edf3ICON_URL_PROPERTYTff7b72] Tff7b72as? Te6edf3JsonPrimitiveTb4b4b4)Tff7b72?.Te6edf3takeIf Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isString Tb4b4b4}Tff7b72?.Te6edf3content
Tff7b72private Tff7b72const Tff7b72val Te6edf3TAG Tff7b72= Ta5d6ff"Ta5d6ffGeoJsonIconsTa5d6ff"
Tff7b72private Tff7b72val Te6edf3URI_SCHEME_PREFIX Tff7b72= Te6edf3RegexTb4b4b4(Ta5d6ff"Ta5d6ff^[A-Za-z][A-Za-z0-9+.-]*:Ta5d6ff"Tb4b4b4)
Served by rngit 1.5.4 - Generated in 0.03s